Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | 변경 요약 |
|---|---|
User 엔티티backend/src/main/java/moadong/user/entity/User.java |
refreshToken: RefreshToken → refreshTokens: List<RefreshToken>로 변경(@Field("refreshTokens"), @Builder.Default로 빈 ArrayList 초기화). 컬렉션 관리 메서드 추가: addRefreshToken, replaceRefreshToken, removeRefreshToken, removeAllRefreshTokens. 기존 updateRefreshToken 제거. List/ArrayList 임포트 추가. |
저장소 쿼리backend/src/main/java/moadong/user/repository/UserRepository.java |
쿼리 메서드명 변경: findUserByRefreshToken_Token(...) → findUserByRefreshTokens_Token(...) (토큰 검색 대상 컬렉션명 반영). |
서비스 로직backend/src/main/java/moadong/user/service/UserCommandService.java |
로그인: 새 토큰을 컬렉션에 추가; 로그아웃: 컬렉션에서 특정 토큰 제거(토큰으로 사용자 조회 변경); 리프레시: 토큰 존재 여부 확인 후 만료 검사 및 replaceRefreshToken 호출; 사용자 업데이트/임시비밀번호(리셋): 모든 리프레시 토큰 제거 및 새 토큰 추가. 쿠키 생성/갱신 로직이 새 토큰 값에 맞게 조정됨. |
Sequence Diagram(s)
sequenceDiagram
participant Client as 클라이언트
participant Service as UserCommandService
participant Repo as UserRepository
participant DB as MongoDB
Note over Service,Repo: 로그인 / 토큰 갱신 흐름 (다중 refreshTokens)
Client->>Service: 로그인 요청 (credentials)
Service->>Repo: findByEmail(...)
Repo->>DB: 사용자 조회
DB-->>Repo: 사용자 도큐먼트 (refreshTokens: [])
Repo-->>Service: User
Service->>Service: generateRefreshToken()
Service->>User: addRefreshToken(newRefreshToken)
Service->>Repo: save(User)
Repo->>DB: 사용자 업데이트 (refreshTokens에 새 토큰 추가)
DB-->>Repo: 저장 완료
Repo-->>Service: 저장된 User
Service-->>Client: 응답 + Set-Cookie (newRefreshToken.token)
Estimated code review effort
🎯 3 (보통) | ⏱️ ~20분
Possibly related issues
- MOA-405: 관리자계정에 다중 refreshToken을 지원한다 — 본 PR은 사용자 엔티티에 다중 refreshToken 컬렉션을 도입하는 작업으로 해당 목표와 일치함.
- [feature] MOA-405 관리자계정에 다중 refreshToken을 지원한다 #911: 단일 refreshToken → 다중 refreshTokens 변경 관련 이슈 — 메서드/쿼리/서비스 로직 업데이트가 이 이슈의 요구사항과 직접적으로 부합함.
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately describes the main change: implementing support for multiple refresh tokens in admin accounts to enable simultaneous login from multiple devices. |
| Linked Issues check | ✅ Passed | The pull request successfully implements the core objective from MOA-405: changing from single to multiple refresh token support with new collection management methods, repository query updates, and service layer modifications. |
| Out of Scope Changes check | ✅ Passed | All changes are directly aligned with the stated objective of adding multiple refresh token support; no unrelated modifications were introduced. |
✨ Finishing touches
- 📝 Generate docstrings
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
feature/#911-admin-multi-refresh-token-MOA-405
📜 Recent review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
backend/src/main/java/moadong/user/service/UserCommandService.java
🔇 Additional comments (6)
backend/src/main/java/moadong/user/service/UserCommandService.java (6)
79-79: 다중 토큰 지원을 위한 올바른 구현입니다.단일 토큰 업데이트에서 컬렉션에 토큰을 추가하는 방식으로 변경되어 여러 기기에서 동시 로그인이 가능합니다.
88-92: 로그아웃 로직이 다중 토큰 구조에 맞게 올바르게 변경되었습니다.특정 토큰만 제거하여 다른 기기의 로그인 세션은 유지됩니다.
123-123: 토큰 갱신 로직이 올바르게 구현되었습니다.특정 토큰만 새 토큰으로 교체하여 다른 기기의 세션에 영향을 주지 않습니다.
148-150: 비밀번호 변경 시 모든 토큰을 제거하는 보안 처리가 적절합니다.모든 기기에서 재로그인을 요구하여 계정 보안을 강화합니다.
154-154: 쿠키 생성이 새로운 RefreshToken 구조에 맞게 올바르게 업데이트되었습니다.
169-169: 임시 비밀번호 발급 시 모든 토큰을 제거하는 보안 처리가 적절합니다.비밀번호 재설정 후 모든 기존 세션을 무효화하여 보안을 강화합니다.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
Test Results75 tests 72 ✅ 19s ⏱️ Results for commit 32ee4ac. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
backend/src/main/java/moadong/user/service/UserCommandService.java (1)
79-80: 토큰 개수 제한 및 정리 전략을 고려하세요.현재 구현에서는 사용자당 리프레시 토큰 개수에 제한이 없습니다. 다음 사항들을 검토하시기 바랍니다:
토큰 개수 제한: 사용자가 로그아웃 없이 계속 로그인하면 토큰이 무제한으로 누적될 수 있습니다. 최대 토큰 개수를 설정하고 오래된 토큰을 자동으로 제거하는 정책을 고려하세요 (예: 최대 5개 기기).
만료된 토큰 정리: 만료된 토큰이 DB에 계속 남아있습니다. 주기적인 정리 작업(scheduled job)이나 로그인 시 만료 토큰 제거 로직을 추가하는 것이 좋습니다.
기기 식별: 현재는 어떤 토큰이 어떤 기기에서 사용되는지 추적할 수 없습니다. 향후 "다른 기기에서 로그아웃" 같은 기능을 위해 기기 정보(User-Agent, 기기명 등)를 RefreshToken에 포함하는 것을 고려하세요.
backend/src/main/java/moadong/user/entity/User.java (2)
107-118: 토큰을 찾지 못한 경우의 처리를 개선하세요.
replaceRefreshToken메서드가oldToken을 찾지 못하면 아무 작업 없이 조용히 반환됩니다. 이는 토큰 교체가 예상되지만 실제로 발생하지 않는 버그를 숨길 수 있습니다.다음 중 하나를 고려하세요:
- 토큰을 찾지 못한 경우 예외를 던지기
- 경고 로그 남기기
- 반환 타입을 boolean으로 변경하여 성공 여부를 알리기
🔎 예외 처리 추가 제안
public void replaceRefreshToken(String oldToken, RefreshToken newToken) { if (this.refreshTokens == null) { this.refreshTokens = new ArrayList<>(); - return; + throw new IllegalStateException("토큰 교체 실패: 리프레시 토큰 목록이 비어있습니다."); } for (int i = 0; i < this.refreshTokens.size(); i++) { if (this.refreshTokens.get(i).getToken().equals(oldToken)) { this.refreshTokens.set(i, newToken); return; } } + throw new IllegalArgumentException("토큰 교체 실패: 기존 토큰을 찾을 수 없습니다."); }
127-133: 전체 토큰 제거 메서드의 null 처리를 단순화할 수 있습니다.현재 구현은
refreshTokens가 null일 때 새 ArrayList를 초기화한 후 바로 반환합니다(129-130행). null인 경우 초기화 없이 바로 반환하거나, null이 아닐 때만 clear를 호출하는 것이 더 명확합니다.🔎 단순화 제안
public void removeAllRefreshTokens() { - if (this.refreshTokens == null) { - this.refreshTokens = new ArrayList<>(); - return; - } - this.refreshTokens.clear(); + if (this.refreshTokens != null) { + this.refreshTokens.clear(); + } }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
backend/src/main/java/moadong/user/entity/User.javabackend/src/main/java/moadong/user/repository/UserRepository.javabackend/src/main/java/moadong/user/service/UserCommandService.java
🔇 Additional comments (9)
backend/src/main/java/moadong/user/repository/UserRepository.java (1)
12-12: 메서드 이름 변경이 적절합니다.
refreshTokens컬렉션 필드와 일치하도록 메서드 이름이 올바르게 변경되었습니다. Spring Data MongoDB가 중첩 필드 쿼리를 정상적으로 처리할 것입니다.backend/src/main/java/moadong/user/service/UserCommandService.java (5)
79-80: 로그인 시 토큰 추가 로직이 올바릅니다.리프레시 토큰을 컬렉션에 추가하는 방식으로 다중 기기 로그인을 지원하도록 변경되었습니다.
88-92: 로그아웃 로직이 적절합니다.특정 리프레시 토큰만 제거하여 다른 기기의 세션에 영향을 주지 않도록 구현되었습니다.
123-124: 토큰 교체 로직이 적절합니다.사용된 리프레시 토큰을 새로운 토큰으로 교체하여 토큰 재사용을 방지합니다.
148-155: 프로필 업데이트 시 모든 토큰을 초기화하는 것은 적절한 보안 조치입니다.사용자 프로필이 변경되면 모든 기기에서 재로그인을 요구하여 보안을 강화합니다.
169-169: 비밀번호 재설정 시 모든 토큰 무효화는 보안 모범 사례입니다.비밀번호가 변경되면 모든 세션을 무효화하여 보안을 강화합니다.
backend/src/main/java/moadong/user/entity/User.java (3)
58-60: 리프레시 토큰 컬렉션 필드 선언이 적절합니다.
@Builder.Default를 사용하여 빈 리스트로 초기화하고, MongoDB 필드 매핑을 명시적으로 지정했습니다.
100-105: 토큰 추가 메서드가 안전하게 구현되었습니다.null 체크는
@Builder.Default로 초기화되어 있어 불필요해 보일 수 있지만, 레거시 데이터나 역직렬화 시나리오에서 방어적 코딩으로 작동합니다.
120-125: 토큰 제거 메서드가 깔끔하게 구현되었습니다.
removeIf를 사용하여 간결하고 읽기 쉬운 코드를 작성했습니다.
backend/src/main/java/moadong/user/service/UserCommandService.java
Outdated
Show resolved
Hide resolved
lepitaaar
left a comment
There was a problem hiding this comment.
refreshtoken 추가할때 레이스컨디션 이슈는 발생할꺼같은데 크리티컬하진 않은것 같습니다~ 리뷰하다 든생각인데 리프레시 토큰 리스트 길이 제한은 나중에 추가하는게 좋아보여요! 수고하셨습니다
#️⃣연관된 이슈
📝작업 내용
다중 리프레시 토큰 지원
고려했던 점
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
새로운 기능
개선 사항
✏️ Tip: You can customize this high-level summary in your review settings.